package com.fingard.dsp.bank.directbank.chanpay01;

import java.net.URL;
import java.util.HashMap;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
import com.fingard.dsp.bank.directbank.chanpay01.chanpay01Util.CjSignHelper;
import com.fingard.dsp.bank.directbank.chanpay01.chanpay01Util.HttpPostBodyMethod;
import com.fingard.dsp.bank.directbank.chanpay01.chanpay01Util.U;
import com.fingard.dsp.bank.directbank.chanpay01.chanpay01Util.Util;
import com.fingard.dsp.bank.directbank.chanpay01.chanpay01Util.CjSignHelper.VerifyResult;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.io.FileHelper;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextReader;

public class ChanPay01BatPayRec extends ChanPay01Base implements IBatPayRec{

	@Override
	public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988)
			throws Exception {
		return d_BatPayRec(p_req1988);
	}
	@Override
	public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188)
			throws Exception {
		return d_BatPayRec(p_req9188);
	}
	
	//批量代收和批量代付提交
	public RetAtsBatPayRec d_BatPayRec(ReqBatPayRec p_reqBat) throws Exception{
		//返回ATS的对象
		RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_reqBat.reqHeader);
		try {
			ActSetItem actItem = getBankConfig().getActSetItem(p_reqBat.ownAct, "");
			if(actItem == null || !FileHelper.existFile(actItem.ownKeyStorePath) || !FileHelper.existFile(actItem.oppCertFilePath)){
				retAts.respCode = "0";
				if(actItem == null){
					retAts.respInfo = "未找到账号"+p_reqBat.ownAct+"的批量商户配置节点";
				}
				else{
					retAts.respInfo = "账号"+p_reqBat.ownAct+"的证书文件不存在";
				}
				retAts.reqSeqID = p_reqBat.reqBatchNO;
				retAts.transState = PaymentState.FAIL_Batch;
				retAts.payInfoCode = FailCode.E9981;
				retAts.writeRetToATS();
				return retAts;
			}
			
			Document doc = DocumentHelper.createDocument();
			Element msgEl = doc.addElement("MESSAGE");

			Element infoEl = msgEl.addElement("INFO");
			if(p_reqBat.reqHeader.transType.equals("1988")){
				infoEl.addElement("TRX_CODE").setText("G10004");//批量付款
			}
			else if(p_reqBat.reqHeader.transType.equals("9188")){
				infoEl.addElement("TRX_CODE").setText("G10003");//批量收款
			}
			infoEl.addElement("VERSION").setText("01");
			infoEl.addElement("MERCHANT_ID").setText(actItem.merchantId);
			infoEl.addElement("REQ_SN").setText(p_reqBat.reqHeader.reqSeqID);
			infoEl.addElement("TIMESTAMP").setText(U.getCurrentTimestamp());
			infoEl.addElement("SIGNED_MSG").setText("");

			Element bodyEl = msgEl.addElement("BODY");

			Element batch = bodyEl.addElement("BATCH");
			String BUSINESS_CODE = this.getBankConfig().getMapAdvanceValue("BUSINESS_CODE_"+p_reqBat.reqHeader.transType, "srcCode", "desCode", p_reqBat.useType);
			batch.addElement("BUSINESS_CODE").setText(BUSINESS_CODE);
			String PRODUCT_CODE = this.getBankConfig().getMapAdvanceValue("PRODUCT_CODE_"+p_reqBat.reqHeader.transType, "srcCode", "desCode", p_reqBat.reqHeader.commandCode);
			batch.addElement("CORP_ACCT_NO").setText(actItem.merchantId);
			batch.addElement("PRODUCT_CODE").setText(PRODUCT_CODE);
			if("1".equals(p_reqBat.isPrivate)){
				//对私 0
				batch.addElement("ACCOUNT_PROP").setText("0");
			}
			else{
				//对公
				batch.addElement("ACCOUNT_PROP").setText("1");
			}
			batch.addElement("SUB_MERCHANT_ID").setText(Format.DateTime14Format.format(p_reqBat.getPayDateTime()));
			if(p_reqBat.reqHeader.commandCode.equals("198801")){
				batch.addElement("TIMELINESS").setText("0");
			}
			else{
				batch.addElement("TIMELINESS").setText("5");
			}
			batch.addElement("TOTAL_CNT").setText(p_reqBat.totalNum);
			batch.addElement("TOTAL_AMT").setText(StringHelper.amountMultiply100(p_reqBat.totalAmt));
			Element detailTitle = bodyEl.addElement("TRANS_DETAILS");

			while(p_reqBat.readRecord()){
				
				Element dtl = detailTitle.addElement("DTL");
				dtl.addElement("SN").setText(U.createUUID());
				if(p_reqBat.reqHeader.transType.equals("1988")){
					//如果是代付
					dtl.addElement("BANK_GENERAL_NAME").setText(p_reqBat.readedDetail.payName);
				}
				else if(p_reqBat.reqHeader.transType.equals("9188")){
					dtl.addElement("BANK_GENERAL_NAME").setText(p_reqBat.readedDetail.recName);
				}
				if(p_reqBat.readedDetail.cardType.equals("1")){
					//存折
					dtl.addElement("ACCOUNT_TYPE").setText("01");
				}
				else if(p_reqBat.readedDetail.cardType.equals("3")){
					//信用卡
					dtl.addElement("ACCOUNT_TYPE").setText("02");
				}
				else {//银行卡
					dtl.addElement("ACCOUNT_TYPE").setText("00");
				}
				if(p_reqBat.reqHeader.transType.equals("1988")){
					dtl.addElement("ACCOUNT_NO").setText(p_reqBat.readedDetail.recAct);
					dtl.addElement("ACCOUNT_NAME").setText(p_reqBat.readedDetail.recName);
				}
				else if(p_reqBat.reqHeader.transType.equals("9188")){
					dtl.addElement("ACCOUNT_NO").setText(p_reqBat.readedDetail.payAct);
					dtl.addElement("ACCOUNT_NAME").setText(p_reqBat.readedDetail.payName);
				}
				String[] tmpPC = p_reqBat.readedDetail.getOppProvinceAndCity();
				
				dtl.addElement("PROVINCE").setText(tmpPC[0]);
				 if(tmpPC[1].equals(tmpPC[0])){
	                	tmpPC[1] = "";
	                }
				dtl.addElement("CITY").setText(tmpPC[1]);
				dtl.addElement("BANK_NAME").setText(p_reqBat.readedDetail.getOppBankLocation());
				//开户行号 与 清算行号 全部一致
				String[] findValues = new String[2];
				findValues[0] = p_reqBat.readedDetail.payBankCode;
				findValues[1] = p_reqBat.readedDetail.payAreaName;//这个方法有问题
				HashMap<String, String> BANK_CODE = this.getBankConfig().getMapAdvanceValues("BankCodeMapping",
						new String[] { "ATSBankCode", "ATSAreaName" }, new String[] { "value" }, findValues);
				if (BANK_CODE != null && BANK_CODE.size() > 0 && BANK_CODE.containsKey("value")) {
					bodyEl.addElement("BANK_CODE").setText(BANK_CODE.get("value"));
					bodyEl.addElement("DRCT_BANK_CODE").setText(BANK_CODE.get("value"));
				}
				else{
					bodyEl.addElement("BANK_CODE").setText("403558000044");
					bodyEl.addElement("DRCT_BANK_CODE").setText("403558000044");
					}
				dtl.addElement("CURRENCY").setText(convertCurToBank(p_reqBat.readedDetail.payCur));
				dtl.addElement("AMOUNT").setText(StringHelper.amountMultiply100(p_reqBat.readedDetail.payAmount));
				dtl.addElement("PROTOCOL_NO").setText(""+System.currentTimeMillis());
				dtl.addElement("ID_TYPE").setText(convertCertTypeToBank(p_reqBat.readedDetail.certType));
				dtl.addElement("ID").setText(p_reqBat.readedDetail.certNum);
				dtl.addElement("SUMMARY").setText(p_reqBat.readedDetail.purpose);
				dtl.addElement("POSTSCRIPT").setText(p_reqBat.readedDetail.purpose);
			}
			String xml = Util.formatXml_UTF8(doc);
			System.out.println("发送报文:"+xml);
			this.WriteBankLogLn("报文：" + U.substringByByte(xml, 512));
			CjSignHelper singHelper = new CjSignHelper(actItem);
			String signMsg = singHelper.signXml$Add(xml);
			HttpClient client = new HttpClient();
			client.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
			client.getParams().setSoTimeout(10 * 60 * 1000);

			URL url = new URL(bankFront.serverURL);
			String urlstr = url.toString();
			HttpPostBodyMethod post = new HttpPostBodyMethod(urlstr, signMsg);

			int statusCode = client.executeMethod(post);
			if (statusCode != HttpStatus.SC_OK) {
				String err = "访问失败！！HTTP_STATUS=" + statusCode;
				
				System.out.println("返回内容为：" + post.getResponseBodyAsString());
				throw new HttpException(err);
			}//if

			String cjRespmsg = post.getResponseBodyAsString();
			// 验证签名
			VerifyResult verifyResult = singHelper.verifyCjServerXml(cjRespmsg);
			if (!verifyResult.result) {
				throw new Exception("验证CJ返回数据的签名失败！" + verifyResult.errMsg);
			}
			System.out.println(cjRespmsg);
			this.WriteBankLogLn("返回报文："+cjRespmsg);
			StringBuilder tmpSbMsg = new StringBuilder();
			XmlTextReader tmpBkReader = loadBankRespXmlReader(cjRespmsg, tmpSbMsg);
			if(tmpBkReader!=null){
				retAts.respCode = "0";
				retAts.respInfo = tmpBkReader.getFirstText("/MESSAGE/INFO/ERR_MSG");
				retAts.reqSeqID = tmpBkReader.getFirstText("/MESSAGE/INFO/REQ_SN");
				retAts.transState = tmpBkReader.getFirstText("/MESSAGE/INFO/RET_CODE");
				retAts.payInfoCode = tmpBkReader.getFirstText("/MESSAGE/INFO/RET_CODE");
			}
			else{
				retAts.respCode = "-1";
				retAts.respInfo = tmpSbMsg.toString();
			}
			
			
		}catch (Exception e) {
			retAts.respCode = "-1";
			retAts.respInfo = e.toString();
			e.printStackTrace();
		}
		if(retAts.respCode.equals("-1") && StringHelper.isNullOrEmpty(retAts.reqSeqID)){
			retAts.reqSeqID = p_reqBat.reqBatchNO;
		}
		retAts.writeRetToATS();
		return retAts;
	}
	@Override
	public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998)
			throws Exception {
		return d_QryBatPayRec(p_req1998);
	}

	@Override
	public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198)
			throws Exception {
		return d_QryBatPayRec(p_req9198);
	}
	//批量代收和批量代付状态查询
		public RetAtsQryBatPayRec d_QryBatPayRec(ReqQryBatPayRec p_reqQryBat) throws Exception{
			//返回ATS的对象
			RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_reqQryBat.reqHeader);
			retAts.respCode = "";
			ActSetItem actItem = getBankConfig().getActSetItem(p_reqQryBat.ownAct, "");
			if(actItem == null){			
				retAts.respCode = "-1";
				retAts.respInfo = "未找到账号"+p_reqQryBat.ownAct+"的批量商户配置节点";
				retAts.writeBeforeDetail();
				retAts.writeAfterDetail();
				return retAts;
			}
			
			Document doc = DocumentHelper.createDocument();
			Element msgEl = doc.addElement("MESSAGE");

			Element infoEl = msgEl.addElement("INFO");
			infoEl.addElement("TRX_CODE").setText("G20002");
			infoEl.addElement("VERSION").setText("01");
			infoEl.addElement("MERCHANT_ID").setText(actItem.merchantId);
			infoEl.addElement("REQ_SN").setText(p_reqQryBat.reqHeader.transSeqID);//当前请求的流水号
			infoEl.addElement("TIMESTAMP").setText(U.getCurrentTimestamp());
			infoEl.addElement("SIGNED_MSG").setText("");

			Element bodyEl = msgEl.addElement("BODY");
			bodyEl.addElement("QRY_REQ_SN").setText(p_reqQryBat.reqBatchNO);//要查询的请求流水号
			//原交易明细号没写
			String cjReqmsg = Util.formatXml_UTF8(doc);
			this.WriteBankLogLn("产生G20002文件上传：" + U.substringByByte(cjReqmsg, 512));
			
			// 签名
			CjSignHelper singHelper = new CjSignHelper(actItem);
			String signMsg = singHelper.signXml$Add(cjReqmsg);
			
		try {
			HttpClient client = new HttpClient();
			client.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
			client.getParams().setSoTimeout(10 * 60 * 1000);

			URL url = new URL(bankFront.serverURL);
			String urlstr = url.toString();
			HttpPostBodyMethod post = new HttpPostBodyMethod(urlstr, signMsg);

			int statusCode = client.executeMethod(post);
			if (statusCode != HttpStatus.SC_OK) {
				String err = "访问失败！！HTTP_STATUS=" + statusCode;
				
				System.out.println("返回内容为：" + post.getResponseBodyAsString());
				throw new HttpException(err);
			}

			String cjRespmsg = post.getResponseBodyAsString();
			System.out.println(cjRespmsg);
			// 验证签名
			VerifyResult verifyResult = singHelper.verifyCjServerXml(cjRespmsg);
			if (!verifyResult.result) {
				throw new Exception("验证CJ返回数据的签名失败！" + verifyResult.errMsg);
			}
			this.WriteBankLogLn("返回报文："+cjRespmsg);
			StringBuilder tmpSbMsg = new StringBuilder();
			XmlTextReader tmpBkReader = loadBankRespXmlReader(cjRespmsg, tmpSbMsg);
			if(tmpBkReader!=null){
				retAts.respCode = "0";
				String RET_CODE1 = tmpBkReader.getFirstText("/MESSAGE/INFO/RET_CODE");
				String ERR_MSG = tmpBkReader.getFirstText("/MESSAGE/INFO/ERR_MSG");
				if(RET_CODE1.equals("0000")){
					//报头成功
					retAts.respCode = "0";
					retAts.respInfo = ERR_MSG;
					retAts.reqSeqID =p_reqQryBat.reqBatchNO ;
					retAts.transState = RET_CODE1;
					retAts.payInfoCode = RET_CODE1;
					retAts.writeBeforeDetail();
					while(tmpBkReader.read("/MESSAGE/BODY/TRANS_DETAILS/DTL")){
						RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();
						if(p_reqQryBat.reqHeader.transType.equals("1998")){
							tmpRetDetail.recAct = tmpBkReader.readedXElement.getSingleText("REC_ACCT_NO");
							tmpRetDetail.recName = tmpBkReader.readedXElement.getSingleText("REC_ACCT_NAME");
						}
						else if(p_reqQryBat.reqHeader.transType.equals("9198")){
							tmpRetDetail.payAct = tmpBkReader.readedXElement.getSingleText("PAY_ACCT_NO");
							tmpRetDetail.payName = tmpBkReader.readedXElement.getSingleText("PAY_ACCT_NAME");
						}
						tmpRetDetail.payAmount = StringHelper.amountDivide100(tmpBkReader.readedXElement.getSingleText("AMOUNT"));
						tmpRetDetail.postScript = tmpBkReader.readedXElement.getSingleText("POSTSCRIPT");
						String DETAIL_RET_CODE = tmpBkReader.readedXElement.getSingleText("RET_CODE");
						tmpRetDetail.result = DETAIL_RET_CODE;
						tmpRetDetail.memo = tmpBkReader.readedXElement.getSingleText("ERR_MSG");
						tmpRetDetail.payInfoCode = DETAIL_RET_CODE;
						retAts.writeRetDetail(tmpRetDetail);
					}
				}
				else if(RET_CODE1.equals("2009")){
					//交易不存在
					retAts.respCode = "-1";
					retAts.respInfo = ERR_MSG;
				}
				else{
					//各种失败
					retAts.respCode="-1";
					retAts.respInfo = ERR_MSG;
				}
				
			}else{
				retAts.respCode="-1";
				retAts.respInfo = cjRespmsg;
			}
			
			} catch (Exception e) {
				retAts.respCode = "-1";
				retAts.respInfo = e.getMessage();
				e.printStackTrace();
			}
			if(retAts.respCode.equals("-1") && StringHelper.isNullOrEmpty(retAts.reqSeqID)){
				retAts.reqSeqID = p_reqQryBat.reqBatchNO;
			}
			if(retAts.respCode.equals("-1")){
				retAts.writeBeforeDetail();
			}
			retAts.writeAfterDetail();
			return retAts;
		}	
}
